/*
 * @(#)LotusDominoReceiverImpl.java
 *
 * Copyright (c) 2005 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */
package com.dcivision.mail.core; 


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Random;

import javax.mail.Message;
import javax.mail.internet.MimeUtility;
import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import lotus.domino.Database;
import lotus.domino.DocumentCollection;
import lotus.domino.NotesException;
import lotus.domino.NotesFactory;
import lotus.domino.Session;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import com.dcivision.dms.DmsErrorConstant;
import com.dcivision.dms.core.EmptyContentException;
import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.ErrorConstant;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.SystemParameterConstant;
import com.dcivision.framework.SystemParameterFactory;
import com.dcivision.framework.TextUtility;
import com.dcivision.mail.bean.EmailAttachment;
import com.dcivision.mail.bean.EmailAttachmentImpl;
import com.dcivision.mail.bean.EmailFolder;
import com.dcivision.mail.bean.EmailMessage;
import com.dcivision.mail.bean.EmailMessageImpl;
import com.dcivision.mail.bean.MailSetting;
import com.dcivision.mail.dao.MailSettingDAObject;

/**
 LotusDominoReceiverImpl.java
 
 This class about receive email.
 
 @author         Rollo Chan
 @company        DCIVision Limited
 @creation date  14/01/2005
 @version        $Revision: 1.1.4.3 $
 */

public class LotusDominoReceiverJournalingImpl extends EmailReceiver implements java.io.Serializable {
  
  public static final String REVISION = "$Revision: 1.1.4.3 $";
  
  private static final Log log = LogFactory.getLog(LotusDominoReceiverJournalingImpl.class);
  
  public final static int PRIORITY_HIGHEST = 5;
  public final static int PRIORITY_HIGH = 4;
  public final static int PRIORITY_NORMAL = 3;
  public final static int PRIORITY_LOW = 2;
  public final static int PRIORITY_LOWEST = 1;
  
  private MailSetting mailSetting = null;
  private EmailFolder folder = null;
  private SessionContainer sessionContainer = null;
  private List mailList = new ArrayList();
  
  public static String SORT_ASC = "ASC";
  public static String SORT_DSC = "DSC";  
  
  private String dbFileHost = "";
  private String dbFilePath = "";
  private String isDelete = "";
  
  private String lotusEmailDir = "";
  private boolean deleteTheEmail = false;  
  
  private LotusDominoReceiverJournalingImpl(SessionContainer sessionContainer) {
    this.sessionContainer = sessionContainer;
  }
  
  public static LotusDominoReceiverJournalingImpl newInstance(SessionContainer sessionContainer) {
    return new LotusDominoReceiverJournalingImpl(sessionContainer);
  }
  
  private void getMailSetting() throws ApplicationException {    
    if (this.mailSetting == null) {
      Connection conn = null;
      
      try {
        conn = com.dcivision.framework.DataSourceFactory.getConnection();
        MailSettingDAObject mailSettingDAO = new MailSettingDAObject(sessionContainer, conn);
        this.mailSetting = (MailSetting)mailSettingDAO.getObjectByUserRecordID(sessionContainer.getUserRecordID());
        this.dbFileHost = this.mailSetting.getParameter1();
        this.dbFilePath = this.mailSetting.getParameter2();
        this.isDelete = this.mailSetting.getParameter3();
        if(isDelete == null || isDelete == ""){
          deleteTheEmail = true;
        }
        this.lotusEmailDir = SystemParameterFactory.getSystemParameter(SystemParameterConstant.DMS_EMAILARCHIVE_LOTUS_SHARE_FOLDER);
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(com.dcivision.framework.ErrorConstant.COMMON_FATAL_ERROR, e);
      } finally {
        try { conn.close(); } catch (Exception ignore) {} finally { conn = null; }
      }
    }
  }
  
  /**
   * Method loadMailList()
   * 
   * @param host
   * @param name
   * @param password
   * @param protocol
   * @return mail list
   * @throws Exception
   */
  
  public List loadMailList(String host, String name, String password, String protocol) throws Exception {
    getMailSetting();
    Session session = null;
    Database databaseObject = null;         
    DocumentCollection  docCol = null;   
    
    try {
      String ior = NotesFactory.getIOR(host);
      log.debug("IOR:" + ior);
      //connect to lotus server
      session = NotesFactory.createSessionWithIOR(ior, name, password);
      
      
      File sourceDirectory = new File(lotusEmailDir);
      log.debug("LotusEmailDir is " +lotusEmailDir);
      File listFileSource[] = sourceDirectory.listFiles();      
      for(int i=0;i<listFileSource.length ;i++){
        if(listFileSource[i].exists() && listFileSource[i].getName().toLowerCase().indexOf(name.toLowerCase())==0  && listFileSource[i].getName().toLowerCase().lastIndexOf(".xml")>0){
          log.debug(listFileSource[i].getName()) ;
          InputSource input = new InputSource();
          InputStream inputStream = null;         
          inputStream = new FileInputStream(listFileSource[i]);
          if(inputStreamIsEmptyContent(inputStream)){
            inputStream.close() ;
            inputStream=null;
            continue;
          }
          
          
          input.setByteStream(inputStream);
          // Create an Document node as the root for the output.
          DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
          DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
          org.w3c.dom.Document indexFile = docBuilder.parse(input);           
          
          String  emailID="";
          String  emailSubject="";
          String  emailSender="";
          String  emailTo="";
          String  emailSendDate="";
          String  emailCC="";
          String  emailSize="";
          String  emailIsTextOly="";
          String  emailBody="";
          String  originalEmailXmlName="";
          
          //get the email attributer
          NodeList doclist = indexFile.getElementsByTagName("Text");
          
          for(int j = 0; j<doclist.getLength();j++ ){
            Node docNode = doclist.item(j);
            Node parentNode = docNode.getParentNode();
            if (docNode != null && docNode.getFirstChild()!=null && parentNode != null) {
              if(docNode!=null&&"MessageID".equals(((Element)parentNode).getAttributeNode("name").getValue())){
                emailID =((docNode.getFirstChild())).getNodeValue();
              }
              if(docNode!=null && docNode.getFirstChild()!=null&&"Subject".equals(((Element)parentNode).getAttributeNode("name").getValue())){
                emailSubject =((docNode.getFirstChild())).getNodeValue();                
              }
              if(docNode!=null && docNode.getFirstChild()!=null&&"From".equals(((Element)parentNode).getAttributeNode("name").getValue())){
                emailSender =((docNode.getFirstChild())).getNodeValue();
              }
              if(docNode!=null && docNode.getFirstChild()!=null&&"To".equals(((Element)parentNode).getAttributeNode("name").getValue())){
                emailTo =((docNode.getFirstChild())).getNodeValue();
              }
              if(docNode!=null && docNode.getFirstChild()!=null&&"DeliveredDate".equals(((Element)parentNode).getAttributeNode("name").getValue())){
                emailSendDate =((docNode.getFirstChild())).getNodeValue();
              }
              if(docNode!=null && docNode.getFirstChild()!=null&&"CC".equals(((Element)parentNode).getAttributeNode("name").getValue())){
                emailCC =((docNode.getFirstChild())).getNodeValue();
              }
              if(docNode!=null && docNode.getFirstChild()!=null&&"odmaProcess".equals(((Element)parentNode).getAttributeNode("name").getValue())){
                emailIsTextOly =((docNode.getFirstChild())).getNodeValue();
              }
              if(docNode!=null && docNode.getFirstChild()!=null&&"Body".equals(((Element)parentNode).getAttributeNode("name").getValue())){
                emailBody =((docNode.getFirstChild())).getNodeValue();
              } 
              if(docNode!=null && docNode.getFirstChild()!=null&&"Size".equals(((Element)parentNode).getAttributeNode("name").getValue())){
                emailSize =((docNode.getFirstChild())).getNodeValue();
              }               
              if(docNode!=null && docNode.getFirstChild()!=null&&"MailDetailFile".equals(((Element)parentNode).getAttributeNode("name").getValue())){
                originalEmailXmlName =((docNode.getFirstChild())).getNodeValue();
              }
            }           
          }          
          if(emailSubject.length() ==0){
            emailSubject = "Not Subject";
          }
          
          EmailMessageImpl emailMessage = EmailMessageImpl.newInstance();              
          emailMessage.setID(new Integer(i));
          emailMessage.setMessageID(emailID);
          emailMessage.setSubject(emailSubject);
          emailMessage.setSender(emailSender);
          //emailMessage.setSendDate(TextUtility.emailSendDate);
          if (emailSendDate != null) {
            java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat(SystemParameterFactory.getSystemParameter(
                SystemParameterConstant.DB_DATETIME_FORMAT),
                new Locale(SystemParameterFactory.getSystemParameter(
                    SystemParameterConstant.LOCALE)));
            java.util.Date date = formatter.parse(emailSendDate);
            emailMessage.setSendDate(date);
          }          
          emailMessage.setTo(TextUtility.noNull(emailTo));
          emailMessage.setCc(TextUtility.noNull(emailCC));
          emailMessage.setSize(TextUtility.parseInteger(emailSize));
          emailMessage.setIsTextOnly(false);   
          emailMessage.setContent(emailBody);
          int priority = PRIORITY_NORMAL;
          emailMessage.setPriority(priority);
          
          
          //add original Email Xml as attachement to dms
          EmailAttachmentImpl emailAttachment = putAttachToCatchFile(originalEmailXmlName,emailSubject+".dxl",-1);
          emailAttachment.setIsOrigEmail(true);
          emailMessage.addAttachment(emailAttachment);
          emailMessage.setHaveAttachment(true);                    
          
          
          // add attachement file to dms
          NodeList attachmentList = indexFile.getElementsByTagName("AttachmentItem");
          List attachList = new ArrayList();            
          for(int j = 0; j<attachmentList.getLength();j++ ){
            Node docNode = attachmentList.item(j);
            Node parentNode = docNode.getParentNode();
            String trueFileName="";
            String attachementFilePath="";
            File attchmentFile;
            if (docNode != null ) {  
              trueFileName = ((Element)docNode).getAttributeNode("Originalfilename").getValue();
              attachementFilePath = ((Element)docNode).getAttributeNode("Filename").getValue();
              emailMessage.addAttachment(putAttachToCatchFile(attachementFilePath,trueFileName,j));
              
            }
          }
          emailMessage.setAnalyzed(true);
          mailList.add(emailMessage);
          
          inputStream.close() ;
          inputStream=null;
          //remove this email xml file.
          if(deleteTheEmail){
            listFileSource[i].delete() ;   
          }
          
        }        
      }      
      
    } catch (NotesException e) {    
      log.error(e, e);
      throw new ApplicationException(DmsErrorConstant.MESSAGE_EMAILARCHIVE_LOGINFAIL, e);
    } catch (Exception e) {
      log.error(e, e);
      throw e;
    } finally {
      try { session.recycle(); } catch (Exception ignore) {} finally { session = null; }
    }    
    
    return mailList;
  }
  
  /**
   * Method  getFolder
   * @return
   */
  
  public EmailFolder getFolder() {
    return this.folder;
  }
  
  
  public EmailMessage getMessageContent(HttpServletRequest request,String mailID,String mailServerType) throws ApplicationException{
    
    EmailMessage emailMessage = null;     
    try {
      List sessEmailList = (List) request.getSession(true).getAttribute("sessEmailList");
      emailMessage = EmailReceiver.getMailByID(sessEmailList, mailID);
    } catch (Exception e) {
      log.error(e, e);
      throw new ApplicationException(ErrorConstant.COMMON_FATAL_ERROR);
    }
    return emailMessage;
  }  
  
  
  /**
   * Method  putAttachToCatchFile
   * @param bodyPart
   * @param sequence
   * @return
   */
  private EmailAttachmentImpl putAttachToCatchFile(String attachFilePath,String truFileName, int sequence) {
    EmailAttachmentImpl emailAttachment = new EmailAttachmentImpl();
    try {
      File attachFile = new File(lotusEmailDir+attachFilePath);
      if(attachFile.exists()){
        long currentTime = new java.util.Date().getTime();
        Random rand = new Random();
        Double randomNum = new Double((Math.random() * 1000));
        String folderName = SystemParameterFactory
        .getSystemParameter(SystemParameterConstant.DMS_EMAILARCHIVE_CACHEFOLDER_PATH);
        File catcheFolder = new File(folderName);
        if (!catcheFolder.exists()) {
          catcheFolder.mkdir();
        }
        String fileName = sessionContainer.getUserRecordID() + "_"
        + currentTime + "_" + randomNum.intValue() + "_" + sequence
        + ".tmp";
        FileOutputStream objfile = new FileOutputStream(folderName
            + fileName);
        InputStream inputStream =  new FileInputStream(attachFile);
        int bufferSize = 8192;
        byte[] buffer = new byte[bufferSize];
        int length = -1;
        int allLength = 0;
        while ((length = inputStream.read(buffer, 0, bufferSize)) != -1) {
          objfile.write(buffer, 0, length);
        }
        inputStream.close();
        inputStream = null;
        objfile.flush();
        objfile.close();
        emailAttachment.setAttachFileName(decodeText(truFileName));
        emailAttachment.setCatchFileName((fileName));
        emailAttachment.setContentID(null);
        emailAttachment.setFileSize((int)attachFile.length());
        // remove this attachFile
        if(deleteTheEmail){          
          attachFile.delete() ;
        }
      }
    } catch (Exception e) {
      log.error(e, e);
    }
    return emailAttachment;
  }
  /**
   * Method  decodeText
   * @param str
   * @return
   */
  public String decodeText(String str){
    if(str == null ){
      return "";
    }  
    if ( str.indexOf("=?x-unknown?") >=0 ){
      str = str.replaceAll("x-unknown","gbk"  );
    }
    try{
      str = MimeUtility.decodeText( str ); 
    }catch( Exception e1){
      return str ;
    }    
    return str;
  }
  private void saveAttach(EmailMessage emailMessage, EmailAttachment emailAttachment) throws Exception {
    emailMessage.addAttachment(emailAttachment);
  }
  
  
  public EmailMessageImpl analysemailEmailMessage(Message msg) throws Exception{
    return null;
  }  
  
  
  public List loadAndProcessMailList(String host, String name, String password,String protocol) throws Exception {
    return loadMailList(host, name, password,protocol);
  }   
  
  
  public EmailMessage getMessageContentNew(HttpServletRequest request,EmailMessage emailMessage,String mailServerType) throws ApplicationException{
    return null;
  }
  
  
  public void setEmailCharset(String charset)throws Exception{    
  }  
  
  
  /**
   * Checks the data inputStream is empty or not.
   * It is mainly use for the creating document and checking document for checking.
   * EmptyContentException is thrown when the inputStream data is empty
   * 
   * @param data InputStream data of the dmsDocument object
   * @throws EmptyContentException
   * @throws ApplicationException
   * @see com.dcivision.dms.core.DocumentOperationManager
   */
  public boolean inputStreamIsEmptyContent(InputStream data) throws EmptyContentException, ApplicationException {
    boolean dataIsEmpty = false;  
    try{
      if (data!=null && data.available()<=0) {
        dataIsEmpty = true;
      }
    } catch (IOException ioe) {
      log.error(ioe, ioe);
    }
    return dataIsEmpty;
  }    
  
  
  
  
}

